//
//  BOCImageCacher.m
//  BOCImageTools
//
//  Created by LeungChaos on 16/5/11.
//  Copyright © 2016年 liang. All rights reserved.
//

#import "BOCImageCacher.h"
#import "BOCNetworkImageManager.h"
#import "NSData+BOCContentType.h"
#import "UIKit+BOC/UIImage+MultiFormat.h"

@interface BOCImageCacher ()
///内存缓存
@property (nonatomic, strong) NSCache *mCache;
///fileManager
@property (nonatomic, weak) NSFileManager *fileManager;
///缓存路径
@property (nonatomic, strong) NSString *cacheFilePath;

@property (nonatomic, strong) dispatch_queue_t cacheQueue;

@end

@implementation BOCImageCacher
/*
 负责一切跟缓存有关的操作
 1.缓存路径  ##
 2.disk缓存 ##
 3.memory缓存 ##
 4.暴力清除缓存 ##
 5.遍历清除过期缓存 ##
 
 提供相关的外部接口
 */
- (instancetype)init
{
    self = [super init];
    if (self) {
        // 获取系统默认的fileManager
        self.fileManager = [NSFileManager defaultManager];
        // 创建专用串行队列
        self.cacheQueue = dispatch_queue_create("com.LeungChaosBOC.ImageCacheQueue", DISPATCH_QUEUE_SERIAL);
        // 创建内存缓存对象
        self.mCache = [[NSCache alloc]init];
        // 初始化文件路径
        self.cacheFilePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"com.LeungChaosBOC.ImageCacheDocument"];
        
        NSLog(@"%@",self);
        // NSCache在模拟器中不会自动清理缓存，建议还是注册一下观察者
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(cleanMemory) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
        
    }
    return self;
}

// 在缓存中找图片
- (UIImage *)imageForURLkey:(NSURL *)key
{
    // 二级缓存
    NSData *data;
    data = [self.mCache objectForKey:objectKeyWithUrl(key)];
    if (data == nil) {
        data = [NSData dataWithContentsOfFile:[self cacheImageFilePathWithKey:key]];
        if (data) {
            [self.mCache setObject:data forKey:objectKeyWithUrl(key)];
        }
    }
    // SDWebImage的 data转图片 里面包括了gif动图的转换
    return  [UIImage sd_imageWithData:data];
}



// 获取整个文件夹的大小
- (void)imageCacheFileSizeBlock:(void(^)(long long size))block
{
    __weak typeof(self) weakSelf = self;
    dispatch_sync(weakSelf.cacheQueue, ^{
        long long size = 0;
        NSDirectoryEnumerator *fileEnum = [weakSelf.fileManager enumeratorAtPath:self.cacheFilePath];
        for (NSString *fileName in fileEnum) {
            NSString *filepath = [weakSelf.cacheFilePath stringByAppendingPathComponent:fileName];
            NSDictionary *attr = [weakSelf.fileManager attributesOfItemAtPath:filepath error:nil];
            size += [attr fileSize];
        }
        dispatch_mainQueue_safely_sync(^{
            block(size);
        });
    });
}

// 保存图片的方法
- (void)saveImageData:(NSData *)data forURl:(NSURL *)url
{
    __weak typeof(self) weakSelf = self;
    [weakSelf.mCache setObject:data forKey:objectKeyWithUrl(url)];
    dispatch_sync(weakSelf.cacheQueue, ^{
        if (![weakSelf.fileManager fileExistsAtPath:weakSelf.cacheFilePath]) {
            [weakSelf.fileManager createDirectoryAtPath:weakSelf.cacheFilePath withIntermediateDirectories:YES attributes:nil error:nil];
        }
        NSString *writeToPath = [weakSelf cacheImageFilePathWithKey:url];
        if ([weakSelf.fileManager createFileAtPath:writeToPath contents:data attributes:nil]) {
            BOCLog(@"write to file-->Seccess");
        } else {
            BOCLog(@"write to file-->Fail");
        }
    });
}

// 暴力清除缓存文件夹
- (void)clearAllImageCacheWithState:(void(^)(BOOL isSeccess))state
{
    __block BOOL seccess;
    __weak typeof(self) weakSelf = self;
    dispatch_sync(weakSelf.cacheQueue, ^{
        [self.mCache removeAllObjects];
        seccess = [weakSelf.fileManager removeItemAtPath:weakSelf.cacheFilePath error:nil];
        [weakSelf.fileManager createDirectoryAtPath:weakSelf.cacheFilePath withIntermediateDirectories:YES attributes:nil error:nil];
        if (state) {
            dispatch_mainQueue_safely_sync(^{
                state(seccess);
            });
        }
    });
}
#pragma mark - <设置磁盘缓存时间和磁盘缓存的大小>
static NSUInteger const maxSize = 1024 * 2; // 100MB
static NSTimeInterval const expiredTimeInterval = 60 * 60 * 24 * 7; // one week

- (void)cleanExpiredFileCompletion:(void(^)())completion
{
    // 遍历文件夹将所有过期的文件删除 >> 如果删除后文件夹尺寸大于maxSize
    __weak typeof(self) weakSelf = self;
    dispatch_sync(weakSelf.cacheQueue, ^{

        NSDirectoryEnumerator *fileEnum = [weakSelf.fileManager enumeratorAtPath:self.cacheFilePath];

        NSMutableDictionary *fileDict = [NSMutableDictionary dictionary];
        
        NSDate *expiredDate = [NSDate dateWithTimeIntervalSinceNow:-expiredTimeInterval];
        
        for (NSString *fileName in fileEnum) {
            
            NSString *filepath = [weakSelf.cacheFilePath stringByAppendingPathComponent:fileName];
            
            NSDictionary *attr = [weakSelf.fileManager attributesOfItemAtPath:filepath error:nil];
            /*
             fileCreationDate -> 创建时间
             fileModificationDate -> 修改时间
             */
            NSDate *creatDate = [attr fileCreationDate];
            // 过期时间
            // 时间差
            NSTimeInterval result = creatDate.timeIntervalSinceReferenceDate - expiredDate.timeIntervalSinceReferenceDate;
            if (result <= 0) {
                [weakSelf.fileManager removeItemAtPath:filepath error:nil];
            } else {
                // 没有被删除的先保存起来
                [fileDict setObject:attr forKey:filepath];
            }
        }
        if ([weakSelf directorySizeBiggerThanMaxSize]) {
            // 继续删除
            // 排序取出所有未删除的filePath
            NSArray *pathArray = [fileDict keysSortedByValueUsingComparator:^NSComparisonResult(NSDictionary * _Nonnull obj1, NSDictionary * _Nonnull obj2) {
                
                return [[obj1 fileCreationDate] compare:[obj2 fileCreationDate]];
                
            }];
            // 删除创建时间最早的
            [pathArray enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                
                [weakSelf.fileManager removeItemAtPath:obj error:nil];
                
                if (![weakSelf directorySizeBiggerThanMaxSize]) {
                    *stop = YES;
                }
            }];
        }
        if (completion) {
            dispatch_mainQueue_safely_sync(^{
                completion();
            });
        }
    });
}

#pragma mark - 私有的方法

- (BOOL)directorySizeBiggerThanMaxSize
{
    NSDictionary *directoryAttr = [self.fileManager attributesOfItemAtPath:self.cacheFilePath error:nil];
    long long directorySize = [directoryAttr fileSize];
    
    if (directorySize > maxSize) {
        return YES;
    } else {
        return NO;
    }
}

// 给一个url路径，生成一个缓存全路径
- (NSString *)cacheImageFilePathWithKey:(NSURL *)key
{
    return [self.cacheFilePath stringByAppendingPathComponent:objectKeyWithUrl(key)];
}

// 清除内存缓存
- (void)cleanMemory
{
    [self.mCache removeAllObjects];
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end
